package api

import (
	"TaskAssignmentSystem/internal/admin/dao"
	"TaskAssignmentSystem/internal/admin/services"
	appservices "TaskAssignmentSystem/internal/app/services"
	"TaskAssignmentSystem/internal/pkg/code"
	"TaskAssignmentSystem/internal/pkg/middleware/handler"
	"TaskAssignmentSystem/internal/pkg/middleware/mysqlhandler"
	"TaskAssignmentSystem/internal/pkg/modelbase"
	Redis "TaskAssignmentSystem/pkg/db/redis"
	"TaskAssignmentSystem/pkg/oss"
	"TaskAssignmentSystem/pkg/timehandler"
	"TaskAssignmentSystem/pkg/utils"
	"errors"
	"fmt"
	"github.com/go-the-way/exl"
	"github.com/kataras/iris/v12"
	"github.com/tealeg/xlsx"
	"github.com/wxnacy/wgo/arrays"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

type SearchProjectListRequest struct {
	SearchText      string   `json:"search_text"`
	Page            int64    `json:"page"`
	PageSize        int64    `json:"page_size"`
	ProjectId       string   `json:"project_id"`
	Status          int      `json:"status" default:"-1"`
	OnlineDateTime  []string `json:"online_date_time"`
	OfflineDateTime []string `json:"offline_date_time"`
	EnumType        int      `json:"enum_type" default:"-1"` //项目类型 0:普通项目 1:一审项目 2:二审项目
}

func init() {
	go RegisterProject()
}

// 新注册用户，根据 项目表-新用户权限[关闭0，开启1]'自动授权
func RegisterProject() {
	for {
		if user, ok := <-appservices.SystemUserProjcetChan; ok {
			fmt.Printf("RegisterProject %s name %s", user.TeamNumber, user.RealName)
			var service services.CommonService[dao.SystemProject]
			service.Query = map[string]interface{}{"new_user_restrtction": 1}
			if projcets, err := service.FindAll(); err == nil {
				var userRestrictionDao dao.Common[dao.SystemUserRestriction]
				for _, projcet := range projcets {
					userRestr := dao.SystemUserRestriction{}
					userRestr.SystemUserId = user.Id
					userRestr.ProjectId = projcet.ProjectId
					userRestr.LowerLimit = projcet.LowerLimit
					userRestr.Limit = projcet.Limit
					userRestr.Cd = uint(projcet.Cd)
					userRestr.DayLimit = uint(projcet.DayLimit)
					userRestr.DayGiveUpLimit = uint(projcet.DayGiveUpLimit)
					userRestrictionDao.CreateOne(userRestr)
				}
			}
		}
	}
}

// @Summary 项目列表
// @Description 获取项目列表数据
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body SearchProjectListRequest true "项目列表参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/list [post]
func ProjectListHandler(ctx iris.Context) {
	var RequestParams SearchProjectListRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var service services.CommonService[dao.SystemProject]
	service.Page = RequestParams.Page
	service.PageSize = RequestParams.PageSize
	service.Query = map[string]interface{}{}

	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	var common dao.Common[dao.SystemAdmin]
	admin, _ := common.First(map[string]interface{}{"id": claims.Id})
	//if claims.Type == 2 {
	var pIds []string
	//处理项目权限
	if len(admin.ProjectPermissions) > 0 {
		for _, permission := range admin.ProjectPermissions {
			pIds = append(pIds, permission)
		}
		service.Query["project_id"] = pIds
	}
	if len(admin.TeamPermissions) > 0 {
		//处理团队权限
		for _, team := range admin.TeamPermissions {
			fmt.Println("team", team)
		}
	}

	//}
	if RequestParams.Status != -1 {
		service.Query["status"] = RequestParams.Status
	}
	if RequestParams.ProjectId != "" {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("project_id LIKE '%%%v%%'", RequestParams.ProjectId))
	}
	if len(RequestParams.OnlineDateTime) > 0 {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("online_date_time BETWEEN '%s' AND '%s'", RequestParams.OnlineDateTime[0], RequestParams.OnlineDateTime[1]))
	}
	if len(RequestParams.OfflineDateTime) > 0 {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("offline_date_time BETWEEN '%s' AND '%s'", RequestParams.OfflineDateTime[0], RequestParams.OfflineDateTime[1]))
	}
	if RequestParams.SearchText != "" {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("title LIKE '%%%v%%'", RequestParams.SearchText))
	}
	if RequestParams.EnumType != -1 {
		service.Query["enum_type"] = RequestParams.EnumType
	}
	service.Order = "sort"
	res, _ := service.SelectList()
	ctx.JSON(utils.Response{
		Code:    200,
		Message: "ok",
		Data:    iris.Map{"count": res.Total, "list": res.Data},
	})
	return
}

type ProjectOneRequest struct {
	ProjectId string `json:"project_id"`
}

func ProjectGetOneHandler(ctx iris.Context) {
	var RequestParams ProjectOneRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var service services.CommonService[dao.SystemProject]
	service.Query = map[string]interface{}{"project_id": RequestParams.ProjectId}
	if res, err := service.First(); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		//如果是普通项目
		if res.EnumType == modelbase.WorkProj {
			//查关联的一审项目
			if utils.StringIsNotEmpty(res.AuditProjectId) {
				service.Query = map[string]interface{}{"project_id": res.AuditProjectId}
				if resOne, err := service.First(); err != nil {
					ctx.JSON(utils.ResponseServerError(err))
					return
				} else {
					//查关联的二审项目
					if utils.StringIsNotEmpty(res.FinalProjectId) {
						service.Query = map[string]interface{}{"project_id": res.FinalProjectId}
						if resTwo, err := service.First(); err != nil {
							ctx.JSON(utils.ResponseServerError(err))
							return
						} else {
							ctx.JSON(utils.ResponseData(map[string]interface{}{"project": res, "project_one": resOne, "project_two": resTwo}))
							return
						}
					} else {
						ctx.JSON(utils.ResponseData(map[string]interface{}{"project": res, "project_one": resOne, "project_two": ""}))
						return
					}
				}
			}
			ctx.JSON(utils.ResponseData(map[string]interface{}{"project": res, "project_one": "", "project_two": ""}))
			return
		} else if res.EnumType == modelbase.AuditProj {
			//如果是一审项目
			//查关联的普通项目
			if utils.StringIsNotEmpty(res.WorkProjectId) {
				service.Query = map[string]interface{}{"project_id": res.WorkProjectId}
				if resNomal, err := service.First(); err != nil {
					ctx.JSON(utils.ResponseServerError(err))
					return
				} else {
					//查关联的二审项目
					if utils.StringIsNotEmpty(res.FinalProjectId) {
						service.Query = map[string]interface{}{"project_id": res.FinalProjectId}
						if resTwo, err := service.First(); err != nil {
							ctx.JSON(utils.ResponseServerError(err))
							return
						} else {
							ctx.JSON(utils.ResponseData(map[string]interface{}{"project": resNomal, "project_one": res, "project_two": resTwo}))
							return
						}
					} else {
						ctx.JSON(utils.ResponseData(map[string]interface{}{"project": resNomal, "project_one": res, "project_two": ""}))
						return
					}
				}
			}
			ctx.JSON(utils.ResponseData(map[string]interface{}{"project": "", "project_one": res, "project_two": ""}))
			return
		} else if res.EnumType == modelbase.FinalProj {
			//如果是二审项目
			//查关联的普通项目
			if utils.StringIsNotEmpty(res.WorkProjectId) {
				service.Query = map[string]interface{}{"project_id": res.WorkProjectId}
				if resNomal, err := service.First(); err != nil {
					ctx.JSON(utils.ResponseServerError(err))
					return
				} else {
					//查关联的一审项目
					if utils.StringIsNotEmpty(res.AuditProjectId) {
						service.Query = map[string]interface{}{"project_id": res.AuditProjectId}
						if resOne, err := service.First(); err != nil {
							ctx.JSON(utils.ResponseServerError(err))
							return
						} else {
							ctx.JSON(utils.ResponseData(map[string]interface{}{"project": resNomal, "project_one": resOne, "project_two": res}))
							return
						}
					} else {
						ctx.JSON(utils.ResponseData(map[string]interface{}{"project": resNomal, "project_one": "", "project_two": res}))
						return
					}
				}
			}
			ctx.JSON(utils.ResponseData(map[string]interface{}{"project": "", "project_one": "", "project_two": res}))
			return
		}
		return
	}
}

type ImportsResponse struct {
	TotalRows   int                `json:"total_rows"`
	SuccessRows int                `json:"success_rows"`
	FailRows    int                `json:"fail_rows"`
	ErrList     []code.ImportError `json:"err_list"`
}

type ReadExcelProject1 struct {
	ProjectId           string `excel:"审核项目ID（必填）"`
	EnumType            int    `excel:"项目类型（1表示一审，2表示2审）"`
	WorkProjectId       string `excel:"被审项目ID（必填）"`
	Title               string `excel:"项目名称（必填）"`
	OnlineDateTime      string `excel:"审核项目上线时间（必填）"`
	OfflineDateTime     string `excel:"项目下线时间（必填）"`
	Category            string `excel:"项目分类（必填）"`
	SlideShowSort       int    `excel:"轮播序号（选填）"`
	Sort                int    `excel:"项目默认排序序号（必填）"`
	Limit               int    `excel:"项目每次领取题目数量上限（必填）"`
	LowerLimit          int    `excel:"项目每次领取题目数量下限（必填）"`
	CountdownAnswer     int64  `excel:"每次领取题目限制时间（必填）"`
	Cd                  int    `excel:"领取题目CD时间（必填）"`
	DayLimit            int    `excel:"每日领取题目上限（必填）"`
	DayGiveUpLimit      int    `excel:"每日放弃题目上限（必填）"`
	GiveUpReasonsStr    string `excel:"放弃原因（必填）"`
	ProjectPrice        string `excel:"项目单价"`
	Describe            string `excel:"项目介绍（超链接可以点击跳转打开新页面）"`
	AuditQuickTemplate  string `excel:"审核快捷快捷输入（必填）"`
	RejectionTimePeriod string `excel:"固定驳回时间（每日此时驳回，用；做分割）"`
	CtrlIncrementUnit   int    `excel:"领取和放弃上限默认增加数值(选填)"`
	CtrlDecreaseUnit    int    `excel:"领取和放弃上限默认减少数据(选填)"`
	OpenPerm            string `excel:"默认开启权限（选填）"`
	ClosePerm           string `excel:"默认关闭权限（选填）"`
}

type ReadExcelProject struct {
	ProjectId        string `excel:"项目ID（必填）"`
	Title            string `excel:"项目名称（必填）"`
	OnlineDateTime   string `excel:"项目上线时间（必填）"`
	OfflineDateTime  string `excel:"项目下线时间（必填）"`
	Category         string `excel:"项目分类（必填）"`
	SlideShowSort    int    `excel:"轮播序号（选填）"`
	Sort             int    `excel:"项目默认排序序号（必填）"`
	Limit            int    `excel:"项目每次领取题目数量上限（必填）"`
	LowerLimit       int    `excel:"项目每次领取题目数量下限（必填）"`
	CountdownAnswer  int64  `excel:"每次领取题目限制完成时间（必填）"`
	Cd               int    `excel:"领取题目CD时间（必填）"`
	DayLimit         int    `excel:"每日领取题目上限（必填）"`
	DayGiveUpLimit   int    `excel:"每日放弃题目上限（必填）"`
	GiveUpReasonsStr string `excel:"放弃原因（必填）"`
	ProjectPrice     string `excel:"项目单价（选填）"`
	Describe         string `excel:"项目描述（选填）"`
}

func (*ReadExcelProject) Configure(rc *exl.ReadConfig)  {}
func (*ReadExcelProject1) Configure(rc *exl.ReadConfig) {}

func ExcelProjectImportsHandler0(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelProject](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		var projectServe services.ProjectService
		projectObjs := make([]dao.SystemProject, len(models)-1)
		var res ImportsResponse
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || model.ProjectId == "" {
				continue
			}
			projectObjs[index].ProjectId = model.ProjectId
			projectObjs[index].Title = model.Title
			OfflineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OfflineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目下线时间[" + model.OfflineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OfflineDateTime = OfflineDateTime
			OnlineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OnlineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目上线时间[" + model.OnlineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OnlineDateTime = OnlineDateTime
			projectObjs[index].Category = model.Category
			projectObjs[index].SlideShowSort = model.SlideShowSort
			projectObjs[index].Sort = model.Sort
			projectObjs[index].Limit = model.Limit
			projectObjs[index].LowerLimit = model.LowerLimit
			projectObjs[index].CountdownAnswer = model.CountdownAnswer
			projectObjs[index].DayLimit = model.DayLimit
			projectObjs[index].DayGiveUpLimit = model.DayGiveUpLimit
			projectObjs[index].Cd = model.Cd
			projectObjs[index].ProjectPrice = model.ProjectPrice
			projectObjs[index].Describe = model.Describe
			projectObjs[index].EnumType = 0
			projectObjs[index].Visibility = 1
			projectObjs[index].OldUserRestrtction = 0
			projectObjs[index].NewUserRestrtction = 0
			for _, item := range strings.Split(model.GiveUpReasonsStr, "；") {
				projectObjs[index].GiveUpReasons = append(projectObjs[index].GiveUpReasons, item)
			}
			if err := projectServe.InsertExcel(model.ProjectId, projectObjs[index]); err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: err.Error()})
			}
			index++
		}
		ctx.JSON(utils.Response{
			Code:    200,
			Message: "ok",
			Data:    res,
		})
		return
	}
}

func ExcelProjectImportsHandler1(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelProject1](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		var projectServe services.ProjectService
		projectObjs := make([]dao.SystemProject, len(models)-1)
		var res ImportsResponse
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || model.ProjectId == "" {
				continue
			}
			projectObjs[index].ProjectId = model.ProjectId
			projectObjs[index].Title = model.Title
			OfflineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OfflineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目下线时间[" + model.OfflineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OfflineDateTime = OfflineDateTime
			OnlineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OnlineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目上线时间[" + model.OnlineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OnlineDateTime = OnlineDateTime
			projectObjs[index].Category = model.Category
			projectObjs[index].SlideShowSort = model.SlideShowSort
			projectObjs[index].Sort = model.Sort
			projectObjs[index].Limit = model.Limit
			projectObjs[index].LowerLimit = model.LowerLimit
			projectObjs[index].CountdownAnswer = model.CountdownAnswer
			projectObjs[index].DayLimit = model.DayLimit
			projectObjs[index].DayGiveUpLimit = model.DayGiveUpLimit
			projectObjs[index].Cd = model.Cd
			projectObjs[index].ProjectPrice = model.ProjectPrice
			projectObjs[index].Describe = model.Describe
			projectObjs[index].EnumType = model.EnumType
			projectObjs[index].WorkProjectId = model.WorkProjectId
			projectObjs[index].CtrlIncrementUnit = model.CtrlIncrementUnit
			projectObjs[index].CtrlDecreaseUnit = model.CtrlDecreaseUnit
			projectObjs[index].OpenPerm = model.OpenPerm
			projectObjs[index].ClosePerm = model.ClosePerm
			projectObjs[index].Visibility = 1
			projectObjs[index].OldUserRestrtction = 0
			projectObjs[index].NewUserRestrtction = 0
			for _, item := range strings.Split(model.GiveUpReasonsStr, "；") {
				projectObjs[index].GiveUpReasons = append(projectObjs[index].GiveUpReasons, item)
			}
			//审核快捷快捷输入（必填）
			for _, item := range strings.Split(model.AuditQuickTemplate, "；") {
				projectObjs[index].AuditQuickTemplate = append(projectObjs[index].AuditQuickTemplate, item)
			}
			//固定驳回时间
			for _, item := range strings.Split(model.RejectionTimePeriod, "；") {
				projectObjs[index].RejectionTimePeriod = append(projectObjs[index].RejectionTimePeriod, item)
			}
			if err := projectServe.InsertExcel(model.WorkProjectId, projectObjs[index]); err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: err.Error()})
				continue
			}
		}
		ctx.JSON(utils.Response{
			Code:    200,
			Message: "ok",
			Data:    res,
		})
		return
	}
}

func ExcelProjectImportsHandler2(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelProject1](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		var projectServe services.ProjectService
		projectObjs := make([]dao.SystemProject, len(models)-1)
		var res ImportsResponse
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || model.ProjectId == "" {
				continue
			}
			projectObjs[index].ProjectId = model.ProjectId
			projectObjs[index].Title = model.Title
			OfflineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OfflineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目下线时间[" + model.OfflineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OfflineDateTime = OfflineDateTime
			OnlineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OnlineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目上线时间[" + model.OnlineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OnlineDateTime = OnlineDateTime
			projectObjs[index].Category = model.Category
			projectObjs[index].SlideShowSort = model.SlideShowSort
			projectObjs[index].Sort = model.Sort
			projectObjs[index].Limit = model.Limit
			projectObjs[index].LowerLimit = model.LowerLimit
			projectObjs[index].CountdownAnswer = model.CountdownAnswer
			projectObjs[index].DayLimit = model.DayLimit
			projectObjs[index].DayGiveUpLimit = model.DayGiveUpLimit
			projectObjs[index].Cd = model.Cd
			projectObjs[index].ProjectPrice = model.ProjectPrice
			projectObjs[index].Describe = model.Describe
			projectObjs[index].EnumType = model.EnumType
			projectObjs[index].WorkProjectId = model.WorkProjectId
			projectObjs[index].CtrlIncrementUnit = model.CtrlIncrementUnit
			projectObjs[index].CtrlDecreaseUnit = model.CtrlDecreaseUnit
			projectObjs[index].OpenPerm = model.OpenPerm
			projectObjs[index].ClosePerm = model.ClosePerm
			projectObjs[index].Visibility = 1
			projectObjs[index].OldUserRestrtction = 0
			projectObjs[index].NewUserRestrtction = 0
			for _, item := range strings.Split(model.GiveUpReasonsStr, "；") {
				projectObjs[index].GiveUpReasons = append(projectObjs[index].GiveUpReasons, item)
			}
			//审核快捷快捷输入（必填）
			for _, item := range strings.Split(model.AuditQuickTemplate, "；") {
				projectObjs[index].AuditQuickTemplate = append(projectObjs[index].AuditQuickTemplate, item)
			}
			//固定驳回时间
			for _, item := range strings.Split(model.RejectionTimePeriod, "；") {
				projectObjs[index].RejectionTimePeriod = append(projectObjs[index].RejectionTimePeriod, item)
			}
			if err := projectServe.InsertExcel(model.WorkProjectId, projectObjs[index]); err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: err.Error()})
				continue
			}
			index++
		}
		ctx.JSON(utils.Response{
			Code:    200,
			Message: "ok",
			Data:    res,
		})
		return
	}
}

type EditProjectVisibilityRequest struct {
	ProjectId string `json:"project_id"`
	Status    uint   `json:"status"`
}

// 项目可见性
func ProjectVisibilityHandler(ctx iris.Context) {
	var RequestParams EditProjectVisibilityRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var projectServe services.ProjectService
	if err := projectServe.ByIdUpdateVisibility(RequestParams.ProjectId, RequestParams.Status); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		ctx.JSON(utils.ResponseOK())
		return
	}
}

// 项目老用户权限
func ProjectOldUserOpenOrCloseHandler(ctx iris.Context) {
	var RequestParams EditProjectVisibilityRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var projectServe services.ProjectService
	if err := projectServe.ByIdUpdateOldUserRestrtction(RequestParams.ProjectId, RequestParams.Status); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		ctx.JSON(utils.ResponseOK())
		return
	}
}

// 项目新用户权限
func ProjectNewUserOpenOrCloseHandler(ctx iris.Context) {
	var RequestParams EditProjectVisibilityRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var projectServe services.ProjectService
	if err := projectServe.ByIdUpdateNewUserRestrtction(RequestParams.ProjectId, RequestParams.Status); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		ctx.JSON(utils.ResponseOK())
		return
	}
}

// @Summary 批量导入项目
// @Description 批量导入项目
// @Tags 项目
// @Accept multipart/form-data
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param file formData file true "批量导入项目参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/excel/imports [post]
func ExcelProjectImportsHandler(ctx iris.Context) {
	// 项目ID（用于关联一审和二审）
	projectId := ctx.FormValue("project_id")
	// 项目类型：0:普通项目 1:一审项目 2:二审项目
	enumTypeStr := ctx.FormValue("enum_type")
	enumType, err := strconv.ParseInt(enumTypeStr, 10, 64)
	if enumTypeStr != "" && err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: "enum_type必须是[0,1,2]"})
		return
	}

	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	fileByte, err := ioutil.ReadAll(file) //获取上传文件字节流
	if err != nil {
		fmt.Println(err)
	}
	xlFile, err := xlsx.OpenBinary(fileByte)
	if err != nil {
		fmt.Printf("open failed: %s\n", err)
	}
	titles := []string{"项目ID（必填）", "项目名称（必填）", "项目上线时间（必填）", "项目下线时间（必填）", "项目分类（必填）", "轮播序号（选填）", "项目默认排序序号（必填）", "项目每次领取题目数量上限（必填）", "项目每次领取题目数量下限（必填）", "每次领取题目限制时间（必填）", "放弃原因（必填）", "每日领取题目上限（必填）", "每日放弃题目上限（必填）", "固定驳回时间（每日此时驳回，用；做分割）", "审核快捷快捷输入（必填）", "领取和放弃上限默认增加数值", "领取和放弃上限默认减少数据", "默认开启权限", "默认关闭权限"}
	var projectServe services.ProjectService
	var res ImportsResponse

	for _, sheet := range xlFile.Sheets {

		for i, row := range sheet.Rows {
			// 初始化错误列表的长度值
			var errListLength = len(res.ErrList)
			//判断excel格式对不对
			if i == 0 {
				for j, cell := range row.Cells {
					if cell.String() != titles[j] {
						fmt.Println("cell.String()", cell.String(), "titles", titles[j])
						ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: fmt.Sprintf("文件表头格式不对,%s", cell.String())})
						return
					}
				}
			}
			//从第三行开始
			if i >= 2 {
				res.TotalRows += 1
				var rowsList []string
				var projectObj dao.SystemProject
				var row_data string
				for j, cell := range row.Cells {
					text := strings.TrimSpace(cell.String())
					row_data += text
					if j != 5 {
						if text == "" && j < len(titles) {
							res.ErrList = append(res.ErrList, code.ImportError{
								Sheet:  sheet.Name,
								Number: i + 1,
								Cell:   j + 1,
								Reason: fmt.Sprintf("第%d行字段%s的值不能为空", i+1, titles[j]),
							})
						}
					}
					rowsList = append(rowsList, text)
				}
				if strings.TrimSpace(row_data) == "" {
					res.TotalRows -= 1
					break
				}

				if len(rowsList) < len(titles) {
					for k := len(rowsList); k < len(titles); k++ {
						res.ErrList = append(res.ErrList, code.ImportError{
							Number: i + 1,
							Cell:   k + 1,
							Reason: fmt.Sprintf("第%d行字段%s的值不能为空", i+1, titles[k]),
						})
					}
				}
				if len(res.ErrList) > errListLength {
					res.FailRows += 1
					continue
				}
				// A 列是项目ID
				projectObj.ProjectId = rowsList[0]
				projectObj.Title = rowsList[1]
				projectObj.OnlineDateTime, err = time.ParseInLocation(timehandler.FormatLayoutTime, rowsList[2], time.Local)
				if err != nil {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Reason: fmt.Sprintf("第%d行字段%s的时间格式错误", i+1, titles[2]),
					})
				}
				projectObj.OfflineDateTime, err = time.ParseInLocation(timehandler.FormatLayoutTime, rowsList[3], time.Local)
				if err != nil {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Reason: fmt.Sprintf("第%d行字段%s的时间格式错误", i+1, titles[3]),
					})
				}
				projectObj.Category = rowsList[4]
				if rowsList[5] != "" {
					projectObj.SlideShowSort, err = strconv.Atoi(rowsList[5])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[5]),
						})
					}
				}
				projectObj.Sort, err = strconv.Atoi(rowsList[6])
				if err != nil {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   6 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[6]),
					})
				}
				if rowsList[7] != "" {
					projectObj.Limit, err = strconv.Atoi(rowsList[7])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   7 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[7]),
						})
					}
				}
				if rowsList[8] != "" {
					projectObj.LowerLimit, err = strconv.Atoi(rowsList[8])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   8 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[8]),
						})
					}
				}
				//添加上下限的数据矫正提示
				if projectObj.LowerLimit > projectObj.Limit {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   8 + 1,
						Reason: "最低下限不能超过最高上限",
					})
				}
				if rowsList[9] != "" {
					atom, err := strconv.Atoi(rowsList[9])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   9 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[9]),
						})
					}
					projectObj.CountdownAnswer = int64(atom)
				}
				// K 列：废弃原因
				if rowsList[10] != "" {
					for _, item := range strings.Split(rowsList[10], "；") {
						projectObj.GiveUpReasons = append(projectObj.GiveUpReasons, item)
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   10 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[10]),
					})
				}
				// 新版增加列
				if rowsList[11] != "" {
					projectObj.DayLimit, err = strconv.Atoi(rowsList[11])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   11 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[11]),
						})
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   11 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[11]),
					})
				}
				if rowsList[12] != "" {
					projectObj.DayGiveUpLimit, err = strconv.Atoi(rowsList[12])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   12 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[12]),
						})
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   12 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[12]),
					})
				}
				// N 列固定驳回时间
				if rowsList[13] != "" {
					for _, item := range strings.Split(rowsList[13], "；") {
						projectObj.RejectionTimePeriod = append(projectObj.RejectionTimePeriod, item)
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   13 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[13]),
					})
				}
				if rowsList[14] != "" {
					for _, item := range strings.Split(rowsList[14], "；") {
						projectObj.AuditQuickTemplate = append(projectObj.AuditQuickTemplate, item)
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   14 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[14]),
					})
				}
				if rowsList[15] != "" {
					projectObj.CtrlIncrementUnit, err = strconv.Atoi(rowsList[15])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   15 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[15]),
						})
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   15 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[15]),
					})
				}
				// Q 列：领取和放弃上限默认减少数值
				if rowsList[16] != "" {
					projectObj.CtrlDecreaseUnit, err = strconv.Atoi(rowsList[16])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   16 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[16]),
						})
					}
				} else {
					res.ErrList = append(res.ErrList, code.ImportError{
						Sheet:  sheet.Name,
						Number: i + 1,
						Cell:   16 + 1,
						Reason: fmt.Sprintf("第%d行字段%s的不能为空", i+1, titles[16]),
					})
				}
				if len(res.ErrList) > errListLength {
					res.FailRows += 1
					continue

				}
				// 项目类型
				projectObj.EnumType = int(enumType)
				// 关联项目ID
				projectObj.WorkProjectId = projectId
				if err := projectServe.InsertExcel(projectId, projectObj); err != nil {
					switch mysqlhandler.MysqlErrCode(err) {
					case mysqlhandler.ErrDuplicateEntryCode:
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: "该条数据已经存在"})
					default:
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: err.Error()})
					}
					res.FailRows += 1
				}
			}
		}
	}
	res.SuccessRows = res.TotalRows - res.FailRows
	ctx.JSON(utils.Response{
		Code:    200,
		Message: "ok",
		Data:    res,
	})
	return
}

// @Summary 批量更新项目
// @Description 批量更新项目
// @Tags 项目
// @Accept multipart/form-data
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param file formData file true "批量更新项目参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/excel/update [post]
func BatchEditProjectHandler(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	fileByte, err := ioutil.ReadAll(file) //获取上传文件字节流
	if err != nil {
		fmt.Println(err)
	}
	xlFile, err := xlsx.OpenBinary(fileByte)
	if err != nil {
		fmt.Printf("open failed: %s\n", err)
	}
	titles := []string{"项目ID（必填）", "项目名称（必填）", "项目上线时间（必填）", "项目下线时间（必填）", "项目分类（必填）", "轮播序号（选填）", "项目默认排序序号（必填）", "项目每次领取题目数量上限（必填）", "项目每次领取题目数量下限（必填）", "每次领取题目限制时间（必填）", "放弃原因（必填）", "每日领取题目上限（必填）", "每日放弃题目上限（必填）", "固定驳回时间（每日此时驳回，用；做分割）", "审核快捷快捷输入（必填）", "领取和放弃上限默认增加数值", "领取和放弃上限默认减少数据", "默认开启权限", "默认关闭权限"}
	var project dao.Common[dao.SystemProject]
	var res ImportsResponse
	for _, sheet := range xlFile.Sheets {
		for i, row := range sheet.Rows {
			var errListLength = len(res.ErrList)
			//判断excel格式对不对
			if i == 0 {
				for j, cell := range row.Cells {
					if cell.String() != titles[j] {
						ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: fmt.Sprintf("文件表头格式不对,%s", cell.String())})
						return
					}
				}
			}

			//从第三行开始
			if i >= 2 {
				res.TotalRows += 1
				var rowsList []string
				var projectObj dao.SystemProject
				//判断改行是不是空的
				var row_data string
				for j, cell := range row.Cells {
					text := strings.TrimSpace(cell.String())
					row_data += text
					if text == "" && j < len(titles) {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   j + 1,
							Reason: fmt.Sprintf("第%d行字段%s的值不能为空", i+1, titles[j]),
						})
					}
					rowsList = append(rowsList, text)
				}
				if strings.TrimSpace(row_data) == "" {
					res.TotalRows -= 1
					break
				}
				if len(rowsList) < len(titles) {
					for k := len(rowsList); k < len(titles); k++ {
						res.ErrList = append(res.ErrList, code.ImportError{
							Number: i + 1,
							Cell:   k + 1,
							Reason: fmt.Sprintf("第%d行字段%s的值不能为空", i+1, titles[k]),
						})
					}
					res.FailRows += 1
					continue
				}
				projectObj.ProjectId = rowsList[0]
				projectObj.Title = rowsList[1]
				if rowsList[2] != "" {
					projectObj.OnlineDateTime, err = time.ParseInLocation(timehandler.FormatLayoutTime, rowsList[2], time.Local)
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: err.Error(),
						})
					}
				}
				if rowsList[3] != "" {
					projectObj.OfflineDateTime, err = time.ParseInLocation(timehandler.FormatLayoutTime, rowsList[3], time.Local)
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: err.Error(),
						})
					}
				}
				projectObj.Category = rowsList[4]
				if rowsList[5] != "" {
					projectObj.SlideShowSort, err = strconv.Atoi(rowsList[5])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: err.Error(),
						})
					}
				}
				if rowsList[6] != "" {
					projectObj.Sort, err = strconv.Atoi(rowsList[6])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   6 + 1,
							Reason: err.Error(),
						})
					}
				}
				if rowsList[7] != "" {
					projectObj.Limit, err = strconv.Atoi(rowsList[7])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   7 + 1,
							Reason: err.Error(),
						})
					}
				}
				if rowsList[8] != "" {
					projectObj.LowerLimit, err = strconv.Atoi(rowsList[8])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   8 + 1,
							Reason: err.Error(),
						})
					}
				}
				if rowsList[9] != "" {
					atom, err := strconv.Atoi(rowsList[9])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   9 + 1,
							Reason: err.Error(),
						})
					}
					projectObj.CountdownAnswer = int64(atom)
				}
				// K 列：废弃原因
				if rowsList[10] != "" {
					for _, item := range strings.Split(rowsList[10], "；") {
						projectObj.GiveUpReasons = append(projectObj.GiveUpReasons, item)
					}
				}
				// 新版增加列
				if rowsList[11] != "" {
					projectObj.DayLimit, err = strconv.Atoi(rowsList[11])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   11 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[11]),
						})
					}
				}
				if rowsList[12] != "" {
					projectObj.DayGiveUpLimit, err = strconv.Atoi(rowsList[12])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   12 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[12]),
						})
					}
				}
				// N 列固定驳回时间
				if rowsList[13] != "" {
					for _, item := range strings.Split(rowsList[13], "；") {
						projectObj.RejectionTimePeriod = append(projectObj.RejectionTimePeriod, item)
					}
				}
				if rowsList[14] != "" {
					for _, item := range strings.Split(rowsList[14], "；") {
						projectObj.AuditQuickTemplate = append(projectObj.AuditQuickTemplate, item)
					}
				}
				if rowsList[15] != "" {
					projectObj.CtrlIncrementUnit, err = strconv.Atoi(rowsList[15])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   15 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[15]),
						})
					}
				}
				// Q 列：领取和放弃上限默认减少数值
				if rowsList[16] != "" {
					projectObj.CtrlDecreaseUnit, err = strconv.Atoi(rowsList[16])
					if err != nil {
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Cell:   16 + 1,
							Reason: fmt.Sprintf("第%d行字段%s的格式错误", i+1, titles[16]),
						})
					}
				}
				if len(res.ErrList) > errListLength {
					res.FailRows += 1
					continue
				}
				if err := project.BatchUpdateWithWhereForObj(map[string]interface{}{"project_id": projectObj.ProjectId}, projectObj).Error; err != nil {

					switch mysqlhandler.MysqlErrCode(err) {
					case mysqlhandler.ErrDuplicateEntryCode:
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: "该条数据已经存在"})
					default:
						res.ErrList = append(res.ErrList, code.ImportError{
							Sheet:  sheet.Name,
							Number: i + 1,
							Reason: err.Error()})
					}
					res.FailRows += 1
				}
			}
		}
	}
	res.SuccessRows = res.TotalRows - res.FailRows
	ctx.JSON(utils.Response{
		Code:    200,
		Message: "ok",
		Data:    res,
	})
	return
}

type ReadExcelUpdateProject struct {
	ProjectId        string `excel:"项目ID（必填）"`
	Title            string `excel:"项目名称（必填）"`
	OnlineDateTime   string `excel:"项目上线时间（必填）"`
	OfflineDateTime  string `excel:"项目下线时间（必填）"`
	Category         string `excel:"项目分类（必填）"`
	SlideShowSort    int    `excel:"轮播序号（必填）"`
	Sort             int    `excel:"项目默认排序序号（必填）"`
	Limit            int    `excel:"项目每次领取题目数量上限（必填）"`
	LowerLimit       int    `excel:"项目每次领取题目数量下限（必填）"`
	CountdownAnswer  int64  `excel:"每次领取题目限制完成时间（必填）"`
	Cd               int    `excel:"领取题目CD时间（必填）"`
	DayLimit         int    `excel:"每日领取题目上限（选填）"`
	DayGiveUpLimit   int    `excel:"每日放弃题目上限（选填）"`
	GiveUpReasonsStr string `excel:"废弃原因（必填）"`
	ProjectPrice     string `excel:"项目单价（必填）"`
	Describe         string `excel:"项目描述（必填）"`
}

func (*ReadExcelUpdateProject) Configure(rc *exl.ReadConfig) {}
func NewBatchEditProjectHandler(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelUpdateProject](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		var project dao.Common[dao.SystemProject]
		var projectDao dao.Common[dao.SystemProject]
		projectObjs := make([]dao.SystemProject, len(models)-1)
		var res ImportsResponse
		var userRestriction dao.Common[dao.SystemUserRestriction]
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || model.ProjectId == "" {
				continue
			}
			projectObjs[index].ProjectId = model.ProjectId
			if utils.StringIsNotEmpty(model.Title) {
				projectObjs[index].Title = model.Title
			}
			if utils.StringIsNotEmpty(model.OfflineDateTime) {
				OfflineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OfflineDateTime, time.Local)
				if err != nil {
					res.ErrList = append(res.ErrList, code.ImportError{
						Number: index + 1,
						Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目下线时间[" + model.OfflineDateTime + "]格式错误"})
					continue
				}
				projectObjs[index].OfflineDateTime = OfflineDateTime
			}
			if utils.StringIsNotEmpty(model.OnlineDateTime) {
				OnlineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OnlineDateTime, time.Local)
				if err != nil {
					res.ErrList = append(res.ErrList, code.ImportError{
						Number: index + 1,
						Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目上线时间[" + model.OnlineDateTime + "]格式错误"})
					continue
				}
				projectObjs[index].OnlineDateTime = OnlineDateTime
			}
			if utils.StringIsNotEmpty(model.Category) {
				projectObjs[index].Category = model.Category
			}
			if model.SlideShowSort > 0 {
				projectObjs[index].SlideShowSort = model.SlideShowSort
			}
			if model.Sort > 0 {
				projectObjs[index].Sort = model.Sort
			}
			if model.Limit > 0 {
				projectObjs[index].Limit = model.Limit
			}
			if model.LowerLimit > 0 {
				projectObjs[index].LowerLimit = model.LowerLimit
			}
			if model.CountdownAnswer > 0 {
				projectObjs[index].CountdownAnswer = model.CountdownAnswer
			}
			//if model.DayLimit > 0 {
			projectObjs[index].DayLimit = model.DayLimit
			//}
			//if model.DayGiveUpLimit > 0 {
			projectObjs[index].DayGiveUpLimit = model.DayGiveUpLimit
			//}
			if model.Cd > 0 {
				projectObjs[index].Cd = model.Cd
			}
			if utils.StringIsNotEmpty(model.ProjectPrice) {
				projectObjs[index].ProjectPrice = model.ProjectPrice
			}
			if utils.StringIsNotEmpty(model.Describe) {
				projectObjs[index].Describe = model.Describe
			}
			projectObjs[index].EnumType = 0
			if utils.StringIsNotEmpty(model.GiveUpReasonsStr) {
				for _, item := range strings.Split(model.GiveUpReasonsStr, "；") {
					projectObjs[index].GiveUpReasons = append(projectObjs[index].GiveUpReasons, item)
				}
			}
			if projectOld, err := project.First(map[string]interface{}{"project_id": model.ProjectId}); err == nil {
				projectObjs[index].Visibility = projectOld.Visibility
				projectObjs[index].OldUserRestrtction = projectOld.OldUserRestrtction
				projectObjs[index].NewUserRestrtction = projectOld.NewUserRestrtction
			}
			projectDao.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, map[string]interface{}{"ctrl_increment_unit": projectObjs[index].CtrlIncrementUnit, "ctrl_decrease_unit": projectObjs[index].CtrlDecreaseUnit})
			if err := project.BatchUpdateWithWhereForObj(map[string]interface{}{"project_id": model.ProjectId}, projectObjs[index]).Error; err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: err.Error()})
			} else {
				updateMap := map[string]interface{}{}
				if model.Limit > 0 {
					updateMap["limit"] = model.Limit
				}
				if model.LowerLimit > 0 {
					updateMap["lower_limit"] = model.LowerLimit
				}
				//if model.DayLimit > 0 {
				updateMap["day_limit"] = model.DayLimit
				//}
				//if model.DayGiveUpLimit > 0 {
				updateMap["day_give_up_limit"] = model.DayGiveUpLimit
				//}
				if model.Cd > 0 {
					updateMap["cd"] = model.Cd
				}
				//if err := userRestriction.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, map[string]interface{}{"lower_limit": model.LowerLimit, "limit": model.Limit}); err != nil {
				if updateMap != nil {
					if err := userRestriction.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, updateMap); err != nil {

					}
				}
			}
			index++
		}
		ctx.JSON(utils.Response{
			Code:    200,
			Message: "ok",
			Data:    res,
		})
		return
	}
}

type ReadExcelProjectUpdate1 struct {
	ProjectId           string `excel:"审核项目ID（必填）"`
	EnumType            int    `excel:"项目类型（1表示一审，2表示2审）（必填）"`
	WorkProjectId       string `excel:"被审项目ID（必填）"`
	Title               string `excel:"项目名称（必填）"`
	OnlineDateTime      string `excel:"审核项目上线时间（必填）"`
	OfflineDateTime     string `excel:"项目下线时间（必填）"`
	Category            string `excel:"项目分类（必填）"`
	SlideShowSort       int    `excel:"轮播序号（必填）"`
	Sort                int    `excel:"项目默认排序序号（必填）"`
	Limit               int    `excel:"项目每次领取题目数量上限（必填）"`
	LowerLimit          int    `excel:"项目每次领取题目数量下限（必填）"`
	CountdownAnswer     int64  `excel:"每次领取题目限制完成时间（必填）"`
	Cd                  int    `excel:"领取题目CD时间（必填）"`
	DayLimit            int    `excel:"每日领取题目上限（选填）"`
	DayGiveUpLimit      int    `excel:"每日放弃题目上限（选填）"`
	GiveUpReasonsStr    string `excel:"放弃原因（必填）"`
	ProjectPrice        string `excel:"项目单价（必填）"`
	Describe            string `excel:"项目介绍（超链接可以点击跳转打开新页面）（必填）"`
	AuditQuickTemplate  string `excel:"审核快捷快捷输入（必填）"`
	RejectionTimePeriod string `excel:"固定驳回时间（每日此时驳回，用；做分割）（必填）"`
	CtrlIncrementUnit   int    `excel:"领取和放弃上限默认增加数值(选填)"`
	CtrlDecreaseUnit    int    `excel:"领取和放弃上限默认减少数据(选填)"`
	OpenPerm            string `excel:"默认开启权限（选填）"`
	ClosePerm           string `excel:"默认关闭权限（选填）"`
}

func (*ReadExcelProjectUpdate1) Configure(rc *exl.ReadConfig) {}
func NewBatchEditProjectHandler1(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelProjectUpdate1](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		var project services.ProjectService
		projectObjs := make([]dao.SystemProject, len(models)-1)
		var res ImportsResponse
		var projectDao dao.Common[dao.SystemProject]
		var userRestriction dao.Common[dao.SystemUserRestriction]
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || model.ProjectId == "" {
				continue
			}
			projectObjs[index].ProjectId = model.ProjectId
			projectObjs[index].Title = model.Title
			OfflineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OfflineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目下线时间[" + model.OfflineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OfflineDateTime = OfflineDateTime
			OnlineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OnlineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目上线时间[" + model.OnlineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OnlineDateTime = OnlineDateTime
			projectObjs[index].Category = model.Category
			projectObjs[index].SlideShowSort = model.SlideShowSort
			projectObjs[index].Sort = model.Sort
			projectObjs[index].Limit = model.Limit
			projectObjs[index].LowerLimit = model.LowerLimit
			projectObjs[index].CountdownAnswer = model.CountdownAnswer
			//if model.DayLimit > 0 {
			projectObjs[index].DayLimit = model.DayLimit
			//}
			//if model.DayGiveUpLimit > 0 {
			projectObjs[index].DayGiveUpLimit = model.DayGiveUpLimit
			//}
			projectObjs[index].Cd = model.Cd
			projectObjs[index].ProjectPrice = model.ProjectPrice
			projectObjs[index].Describe = model.Describe
			projectObjs[index].EnumType = model.EnumType
			projectObjs[index].WorkProjectId = model.WorkProjectId
			projectObjs[index].CtrlIncrementUnit = model.CtrlIncrementUnit
			projectObjs[index].CtrlDecreaseUnit = model.CtrlDecreaseUnit
			projectObjs[index].OpenPerm = model.OpenPerm
			projectObjs[index].ClosePerm = model.ClosePerm
			for _, item := range strings.Split(model.GiveUpReasonsStr, "；") {
				projectObjs[index].GiveUpReasons = append(projectObjs[index].GiveUpReasons, item)
			}
			//审核快捷快捷输入（必填）
			for _, item := range strings.Split(model.AuditQuickTemplate, "；") {
				projectObjs[index].AuditQuickTemplate = append(projectObjs[index].AuditQuickTemplate, item)
			}
			//固定驳回时间
			for _, item := range strings.Split(model.RejectionTimePeriod, "；") {
				projectObjs[index].RejectionTimePeriod = append(projectObjs[index].RejectionTimePeriod, item)
			}
			/*if err := project.BatchUpdateWithWhereForObj(model.ProjectId, projectObjs[index]).Error; err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: fmt.Sprintf("项目Id[%s]修改错误", model.ProjectId)})
				continue
			}*/
			if projectOld, err := projectDao.First(map[string]interface{}{"project_id": model.ProjectId}); err == nil {
				projectObjs[index].Visibility = projectOld.Visibility
				projectObjs[index].OldUserRestrtction = projectOld.OldUserRestrtction
				projectObjs[index].NewUserRestrtction = projectOld.NewUserRestrtction
			}
			projectDao.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, map[string]interface{}{"ctrl_increment_unit": projectObjs[index].CtrlIncrementUnit, "ctrl_decrease_unit": projectObjs[index].CtrlDecreaseUnit})
			if err := project.BatchUpdateWithWhereForObj(model.ProjectId, projectObjs[index]); err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: fmt.Sprintf("项目Id[%s]修改错误", model.ProjectId)})
				continue
			} else {
				updateMap := map[string]interface{}{}
				updateMap["lower_limit"] = model.LowerLimit
				updateMap["limit"] = model.Limit
				//if model.DayLimit > 0 {
				updateMap["day_limit"] = model.DayLimit
				//}
				//if model.DayGiveUpLimit > 0 {
				updateMap["day_give_up_limit"] = model.DayGiveUpLimit
				//}
				if model.Cd > 0 {
					updateMap["cd"] = model.Cd
				}
				if err := userRestriction.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, updateMap); err != nil {

				}
			}
		}
		ctx.JSON(utils.Response{
			Code:    200,
			Message: "ok",
			Data:    res,
		})
		return
	}
}

func NewBatchEditProjectHandler2(ctx iris.Context) {
	_, handle, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelProjectUpdate1](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		var project services.ProjectService
		projectObjs := make([]dao.SystemProject, len(models)-1)
		var res ImportsResponse
		var projectDao dao.Common[dao.SystemProject]
		var userRestriction dao.Common[dao.SystemUserRestriction]
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || model.ProjectId == "" {
				continue
			}
			projectObjs[index].ProjectId = model.ProjectId
			projectObjs[index].Title = model.Title
			OfflineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OfflineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目下线时间[" + model.OfflineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OfflineDateTime = OfflineDateTime
			OnlineDateTime, err := time.ParseInLocation(timehandler.FormatLayoutTime, model.OnlineDateTime, time.Local)
			if err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: "项目ID=[" + projectObjs[index].ProjectId + "]，项目上线时间[" + model.OnlineDateTime + "]格式错误"})
				continue
			}
			projectObjs[index].OnlineDateTime = OnlineDateTime
			projectObjs[index].Category = model.Category
			projectObjs[index].SlideShowSort = model.SlideShowSort
			projectObjs[index].Sort = model.Sort
			projectObjs[index].Limit = model.Limit
			projectObjs[index].LowerLimit = model.LowerLimit
			projectObjs[index].CountdownAnswer = model.CountdownAnswer
			//if model.DayLimit > 0 {
			projectObjs[index].DayLimit = model.DayLimit
			//}
			//if model.DayGiveUpLimit > 0 {
			projectObjs[index].DayGiveUpLimit = model.DayGiveUpLimit
			//}
			projectObjs[index].Cd = model.Cd
			projectObjs[index].ProjectPrice = model.ProjectPrice
			projectObjs[index].Describe = model.Describe
			projectObjs[index].EnumType = model.EnumType
			projectObjs[index].WorkProjectId = model.WorkProjectId
			projectObjs[index].CtrlIncrementUnit = model.CtrlIncrementUnit
			projectObjs[index].CtrlDecreaseUnit = model.CtrlDecreaseUnit
			projectObjs[index].OpenPerm = model.OpenPerm
			projectObjs[index].ClosePerm = model.ClosePerm
			for _, item := range strings.Split(model.GiveUpReasonsStr, "；") {
				projectObjs[index].GiveUpReasons = append(projectObjs[index].GiveUpReasons, item)
			}
			//审核快捷快捷输入（必填）
			for _, item := range strings.Split(model.AuditQuickTemplate, "；") {
				projectObjs[index].AuditQuickTemplate = append(projectObjs[index].AuditQuickTemplate, item)
			}
			//固定驳回时间
			for _, item := range strings.Split(model.RejectionTimePeriod, "；") {
				projectObjs[index].RejectionTimePeriod = append(projectObjs[index].RejectionTimePeriod, item)
			}
			/*if err := project.BatchUpdateWithWhereForObj(model.ProjectId, projectObjs[index]).Error; err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: fmt.Sprintf("项目Id[%s]修改错误", model.ProjectId)})
				continue
			}*/
			if projectOld, err := projectDao.First(map[string]interface{}{"project_id": model.ProjectId}); err == nil {
				projectObjs[index].Visibility = projectOld.Visibility
				projectObjs[index].OldUserRestrtction = projectOld.OldUserRestrtction
				projectObjs[index].NewUserRestrtction = projectOld.NewUserRestrtction
			}
			projectDao.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, map[string]interface{}{"ctrl_increment_unit": projectObjs[index].CtrlIncrementUnit, "ctrl_decrease_unit": projectObjs[index].CtrlDecreaseUnit})
			if err := project.BatchUpdateWithWhereForObj(model.ProjectId, projectObjs[index]); err != nil {
				res.ErrList = append(res.ErrList, code.ImportError{
					Number: index + 1,
					Reason: fmt.Sprintf("项目Id[%s]修改错误", model.ProjectId)})
				continue
			} else {
				updateMap := map[string]interface{}{}
				updateMap["lower_limit"] = model.LowerLimit
				updateMap["limit"] = model.Limit
				//if model.DayLimit > 0 {
				updateMap["day_limit"] = model.DayLimit
				//}
				//if model.DayGiveUpLimit > 0 {
				updateMap["day_give_up_limit"] = model.DayGiveUpLimit
				//}
				if model.Cd > 0 {
					updateMap["cd"] = model.Cd
				}
				if err := userRestriction.BatchUpdateWithWhere(map[string]interface{}{"project_id": model.ProjectId}, updateMap); err != nil {

				}
			}
			index++
		}
		ctx.JSON(utils.Response{
			Code:    200,
			Message: "ok",
			Data:    res,
		})
		return
	}
}

type EditProjectStatusRequest struct {
	Id     uint `json:"id"`
	Status int  `json:"status"`
}

// @Summary 项目状态编辑
// @Description 项目状态编辑
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body EditProjectStatusRequest true "项目状态编辑参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/status/edit [post]
func EditProjectStatusHandler(ctx iris.Context) {
	var RequestParams EditProjectStatusRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var projectServe services.CommonService[dao.SystemProject]
	projectServe.Query = map[string]interface{}{"id": RequestParams.Id}
	var status int
	switch RequestParams.Status {
	case 0:
		status = 0
	case 1:
		status = 1
	case 2:
		status = 2
	default:
		status = 0

	}
	if err := projectServe.Update(map[string]interface{}{"status": status}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: 200, Message: "ok", Data: "ok"})
		return
	}
}

type DeleteProjectRequest struct {
	Id uint `json:"id" validate:"required"`
}

// @Summary 删除项目
// @Description 删除项目
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body DeleteProjectRequest true "删除项目参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/del [post]
func DeleteProjectHandler(ctx iris.Context) {
	var RequestParams DeleteProjectRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	//判断权限
	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	/*if claims.Type == 2 {
		ctx.JSON(utils.ResponseError{Code: 403, Message: "权限不够"})
		return
	}*/
	var projectServe services.ProjectService
	if err := projectServe.RemoveById(RequestParams.Id); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: 200, Message: "ok", Data: "ok"})
		return
	}
}

// @Summary 上传项目封面
// @Description 上传项目封面
// @Tags 项目
// @Accept multipart/form-data
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param file formData file true "上传项目封面参数"
// @Param id path uint true "上传项目封面参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/cover/upload/{id} [post]
func ProjectCoverUploadHandler(ctx iris.Context) {
	id, err := ctx.Params().GetUint("id")
	if err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	file, fileHeader, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusBadRequest, Message: err.Error()})
		return
	}
	//限制上传文件大小问题
	if fileHeader.Size > int64(utils.MaxCoverSize) {
		ctx.JSON(utils.ResponseError{Code: iris.StatusBadRequest, Message: fmt.Sprintf("文件超出限制大小%vMB", utils.MaxCoverSize/iris.MB)})
		return
	}
	//限制上传文件格式
	if index := arrays.ContainsString([]string{"jpg", "jpeg", "png"}, filepath.Ext(fileHeader.Filename)[1:]); index == -1 {
		ctx.JSON(utils.ResponseError{Code: iris.StatusBadRequest, Message: "文件格式不对"})
		return
	}

	defer file.Close()

	fileByte, err := ioutil.ReadAll(file) //获取上传文件字节流
	fileName := fmt.Sprintf("task-assign/%d/cover/%s", id, fileHeader.Filename)

	ossClient := oss.BucketClient{}
	ossClient.UpBytes(fileByte, fileName)
	var project services.CommonService[dao.SystemProject]
	project.Query = map[string]interface{}{"id": id}
	if err := project.Update(map[string]interface{}{"cover": fmt.Sprintf("%s/%s", utils.ServerConf.AliOssConf.CallBackHost, fileName)}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: fmt.Sprintf("%s/%s", utils.ServerConf.AliOssConf.CallBackHost, fileName)})
		return
	}
}

// @Summary 上传项目Banner
// @Description 上传项目Banner
// @Tags 项目
// @Accept multipart/form-data
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param file formData file true "上传项目Banner参数"
// @Param id path uint true "上传项目Banner参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/banner/upload/{id} [post]
func ProjectBannerUploadHandler(ctx iris.Context) {
	id, err := ctx.Params().GetUint("id")
	if err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	file, fileHeader, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusBadRequest, Message: err.Error()})
		return
	}
	//限制上传文件大小问题
	if fileHeader.Size > int64(utils.MaxCoverSize) {
		ctx.JSON(utils.ResponseError{Code: iris.StatusBadRequest, Message: fmt.Sprintf("文件超出限制大小%vMB", utils.MaxCoverSize/iris.MB)})
		return
	}
	//限制上传文件格式
	if index := arrays.ContainsString([]string{"jpg", "jpeg", "png"}, filepath.Ext(fileHeader.Filename)[1:]); index == -1 {
		ctx.JSON(utils.ResponseError{Code: iris.StatusBadRequest, Message: "文件格式不对"})
		return
	}

	defer file.Close()

	fileByte, err := ioutil.ReadAll(file) //获取上传文件字节流
	fileName := fmt.Sprintf("task-assign/%d/banner/%s", id, fileHeader.Filename)

	ossClient := oss.BucketClient{}
	ossClient.UpBytes(fileByte, fileName)
	var project services.CommonService[dao.SystemProject]
	project.Query = map[string]interface{}{"id": id}
	if err := project.Update(map[string]interface{}{"banner": fmt.Sprintf("%s/%s", utils.ServerConf.AliOssConf.CallBackHost, fileName)}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: fmt.Sprintf("%s/%s", utils.ServerConf.AliOssConf.CallBackHost, fileName)})
		return
	}
}

type SearchIdsRequest struct {
	SearchText string `json:"search_text"`
	TP         int    `json:"tp"` // 0项目 1 团队 2 所有团队
}

// @Summary 搜索项目或团队Id列表
// @Description 搜索项目或团队Id列表
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body SearchIdsRequest true "搜索项目或团队Id列表参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/ids/list [post]
func ProjectTeamIdsHandler(ctx iris.Context) {
	var RequestParams SearchIdsRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	type SystemProject struct {
		ProjectId string `json:"project_id"`
	}
	type SystemUser struct {
		TeamNumber string `json:"team_number"`
	}
	if RequestParams.TP == 0 {
		var common services.CommonService[SystemProject]
		field := fmt.Sprintf("project_id")
		common.SelectField = &field
		common.PageSize = -1
		if RequestParams.SearchText != "" {
			common.WhereStr = append(common.WhereStr, fmt.Sprintf("project_id LIKE '%%%v%%'", RequestParams.SearchText))
		}

		if res, err := common.SelectList(); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			var result []string
			for _, project := range res.Data {
				result = append(result, project.ProjectId)
			}
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: result})
			return
		}
	} else if RequestParams.TP == 1 {

		var common services.CommonService[SystemUser]
		field := fmt.Sprintf("team_number")
		common.SelectField = &field
		if RequestParams.SearchText != "" {
			common.WhereStr = append(common.WhereStr, fmt.Sprintf("team_number LIKE '%%%v%%'", RequestParams.SearchText))
		}
		if res, err := common.SelectList(); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			var result []string
			for _, project := range res.Data {
				if arrays.ContainsString(result, project.TeamNumber) == -1 {
					result = append(result, project.TeamNumber)
				}
			}
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: result})
			return
		}
	} else {
		var common dao.Common[dao.SystemTeam]
		if list, err := common.FindAll(map[string]interface{}{}); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			var result []string
			for _, team := range list {
				if arrays.ContainsString(result, team.TeamNumber) == -1 {
					result = append(result, team.TeamNumber)
				}
			}
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: result})
			return
		}
	}

}

type EditProjectHintRequest struct {
	Id      uint   `json:"id"`
	Content string `json:"content"`
}

// @Summary 项目提示配置
// @Description 项目提示配置
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body EditProjectHintRequest true "项目提示配置参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /admin/project/hint/edit [post]
func EditProjectHintHandler(ctx iris.Context) {
	var RequestParams EditProjectHintRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var hint dao.Common[dao.SystemProject]
	hint.Query = map[string]interface{}{"id": RequestParams.Id}
	if err := hint.Update(map[string]interface{}{"hint": RequestParams.Content}).Error; err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.StatusText(iris.StatusOK)})
		return
	}
}

type EditProjectInfoRequest struct {
	Id                       uint   `json:"id"`
	Visibility               string `json:"visibility"`                 //可见性 0 可见 1 不可见（需要有权限）
	OldUserRestrtction       string `json:"old_user_restrtction"`       //老用户权限[关闭0，开启1]
	NewUserRestrtction       string `json:"new_user_restrtction"`       //新用户权限[关闭0，开启1]
	ProjectPrice             string `json:"project_price"`              //项目单价
	Describe                 string `json:"describe"`                   //项目描述
	SpecialClassificationOne string `json:"special_classification_one"` //特殊分类1(0-关闭,1-开启)
	SpecialClassificationTwo string `json:"special_classification_two"` //特殊分类2(0-关闭,1-开启)
	Sort                     string `json:"sort"`                       //排序
}

func EditProjectInfoHandler(ctx iris.Context) {
	var RequestParams EditProjectInfoRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var projectServe services.CommonService[dao.SystemProject]
	projectServe.Query = map[string]interface{}{"id": RequestParams.Id}
	updateMap := map[string]interface{}{}
	if utils.StringIsNotEmpty(RequestParams.Visibility) {
		updateMap["visibility"] = RequestParams.Visibility
	}
	if utils.StringIsNotEmpty(RequestParams.OldUserRestrtction) {
		updateMap["old_user_restrtction"] = RequestParams.OldUserRestrtction
	}
	if utils.StringIsNotEmpty(RequestParams.NewUserRestrtction) {
		updateMap["new_user_restrtction"] = RequestParams.NewUserRestrtction
	}
	if utils.StringIsNotEmpty(RequestParams.ProjectPrice) {
		updateMap["project_price"] = RequestParams.ProjectPrice
	}
	if utils.StringIsNotEmpty(RequestParams.Describe) {
		updateMap["describe"] = RequestParams.Describe
	}
	if utils.StringIsNotEmpty(RequestParams.SpecialClassificationOne) {
		updateMap["special_classification_one"] = RequestParams.SpecialClassificationOne
	}
	if utils.StringIsNotEmpty(RequestParams.SpecialClassificationTwo) {
		updateMap["special_classification_two"] = RequestParams.SpecialClassificationTwo
	}
	if utils.StringIsNotEmpty(RequestParams.Sort) {
		updateMap["sort"] = RequestParams.Sort
	}
	if err := projectServe.Update(updateMap); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: 200, Message: "ok", Data: "ok"})
		return
	}
}

func ProjectCoverDelHandler(ctx iris.Context) {
	id, err := ctx.Params().GetUint("id")
	if err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var project services.CommonService[dao.SystemProject]
	project.Query = map[string]interface{}{"id": id}
	if err := project.Update(map[string]interface{}{"cover": ""}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK)})
		return
	}
}

func ProjectBannerDelHandler(ctx iris.Context) {
	id, err := ctx.Params().GetUint("id")
	if err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var project services.CommonService[dao.SystemProject]
	project.Query = map[string]interface{}{"id": id}
	if err := project.Update(map[string]interface{}{"banner": ""}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK)})
		return
	}
}

type ExportAnswerProject struct {
	ProjectId       string           `excel:"项目ID"`             //项目自定义Id
	Title           string           `excel:"项目名称"`             //项目标题
	OnlineDateTime  time.Time        `excel:"项目上线时间"`           //上线时间
	OfflineDateTime time.Time        `excel:"项目下线时间"`           //下线时间
	Category        string           `excel:"项目分类"`             //分类
	SlideShowSort   int              `excel:"轮播序号"`             //轮播图排序序号
	Sort            int              `excel:"项目默认排序序号"`         //排序
	Limit           int              `excel:"项目每次领取题目数量上限（必填）"` //用户可领取题目的上限限制
	LowerLimit      int              `excel:"项目每次领取题目数量下限"`     //用户领取题目的下限限制
	CountdownAnswer int64            `excel:"每次领取题目限制完成时间"`     //答题倒计时，时长
	Cd              int              `excel:"领取题目CD时间"`         //领取题目CD时间（必填）
	DayLimit        int              `excel:"每日领取题目上限"`         //用户每日领取题目的上限
	DayGiveUpLimit  int              `excel:"每日放弃题目上限"`         //用户每日放弃题目的上限
	GiveUpReasons   code.SliceString `excel:"废弃原因"`             //放弃原因列表
	ProjectPrice    string           `excel:"项目单价"`             //项目单价
	Describe        string           `excel:"项目描述"`             //项目描述
}

type ExportAnswerProjectRequest struct {
	Ids []int `json:"ids"`
}

func (*ExportAnswerProject) Configure(rc *exl.WriteConfig) {}
func ExportAnswerProjectHandler(ctx iris.Context) {
	var RequestParams ExportAnswerProjectRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var serve dao.Common[dao.SystemProject]
	queryMap := map[string]interface{}{}
	if len(RequestParams.Ids) > 0 {
		queryMap["id"] = RequestParams.Ids
	} else {
		queryMap["enum_type"] = modelbase.WorkProj
	}

	if exportData, err := serve.FindAll(queryMap); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		exportLists := make([]*ExportAnswerProject, len(exportData))
		for i, export := range exportData {
			exportLists[i] = &ExportAnswerProject{}
			exportLists[i].ProjectId = export.ProjectId
			exportLists[i].Title = export.Title
			exportLists[i].OnlineDateTime = export.OnlineDateTime
			exportLists[i].OfflineDateTime = export.OfflineDateTime
			exportLists[i].Category = export.Category
			exportLists[i].SlideShowSort = export.SlideShowSort
			exportLists[i].Sort = export.Sort
			exportLists[i].Limit = export.Limit
			exportLists[i].LowerLimit = export.LowerLimit
			exportLists[i].CountdownAnswer = export.CountdownAnswer
			exportLists[i].Cd = export.Cd
			exportLists[i].DayLimit = export.DayLimit
			exportLists[i].DayGiveUpLimit = export.DayGiveUpLimit
			exportLists[i].GiveUpReasons = export.GiveUpReasons
			exportLists[i].ProjectPrice = export.ProjectPrice
			exportLists[i].Describe = export.Describe
		}

		unix := time.Now().UnixNano()
		if err := exl.Write(fmt.Sprintf("./export/export_answer_project_records_%d.xlsx", unix), exportLists); err != nil {
			fmt.Println("write excel err:" + err.Error())
			return
		}
		tempFilename := fmt.Sprintf("./export/export_answer_project_records_%d.xlsx", unix)
		//删除本地临时文件
		defer os.Remove(tempFilename)
		bucketClient := oss.BucketClient{}
		readFile, _ := ioutil.ReadFile(fmt.Sprintf("./export/export_answer_project_records_%d.xlsx", unix))
		bucketClient.UpBytes(readFile, fmt.Sprintf("task-assign/export/export_answer_project_records_%d.xlsx", unix))
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: fmt.Sprintf("%s/task-assign/export/export_answer_project_records_%d.xlsx", utils.ServerConf.AliOssConf.CallBackHost, unix)})
		return
	}
}

type ExportAuditProject struct {
	ProjectId           string           `excel:"审核项目ID（必填）"`           //项目自定义Id
	EnumType            int              `excel:"项目类型（1表示一审，2表示2审）"`    //项目类型 0:普通项目 1:一审项目 2:二审项目
	WorkProjectId       string           `excel:"被审项目ID（必填）"`           //关联普通项目ID
	Title               string           `excel:"项目名称（必填）"`             //项目标题
	OnlineDateTime      time.Time        `excel:"审核项目上线时间（必填）"`         //上线时间
	OfflineDateTime     time.Time        `excel:"项目下线时间（必填）"`           //下线时间
	Category            string           `excel:"项目分类（必填）"`             //分类
	SlideShowSort       int              `excel:"轮播序号（选填）"`             //轮播图排序序号
	Sort                int              `excel:"项目默认排序序号（必填）"`         //排序
	Limit               int              `excel:"项目每次领取题目数量上限（必填）"`     //用户可领取题目的上限限制
	LowerLimit          int              `excel:"项目每次领取题目数量下限（必填）"`     //用户领取题目的下限限制
	CountdownAnswer     int64            `excel:"每次领取题目限制时间（必填）"`       //答题倒计时，时长
	Cd                  int              `excel:"领取题目CD时间（必填）"`         //领取题目CD时间（必填）
	DayLimit            int              `excel:"每日领取题目上限（必填）"`         //用户每日领取题目的上限
	DayGiveUpLimit      int              `excel:"每日放弃题目上限（必填）"`         //用户每日放弃题目的上限
	GiveUpReasons       code.SliceString `excel:"放弃原因（必填）"`             //放弃原因列表
	ProjectPrice        string           `excel:"项目单价"`                 //项目单价
	Describe            string           `excel:"项目介绍（超链接可以点击跳转打开新页面）"` //项目描述
	AuditQuickTemplate  code.SliceString `excel:"审核快捷快捷输入（必填）"`         //审核快速输入列表
	RejectionTimePeriod code.SliceString `excel:"固定驳回时间（每日此时驳回，用；做分割）"` //固定驳回时间
	CtrlIncrementUnit   int              `excel:"领取和放弃上限默认增加数值(选填)"`    //领取/放弃上限递增单位
	CtrlDecreaseUnit    int              `excel:"领取和放弃上限默认减少数据(选填)"`    //领取/放弃上限递减单位
	OpenPerm            string           `excel:"默认开启权限（选填）"`           //默认开启权限（选填）
	ClosePerm           string           `excel:"默认关闭权限（选填）"`           //默认关闭权限（选填）
}

type ExportAuditProjectRequest struct {
	Ids      []int `json:"ids"`
	EnumType int   `json:"enum_type" validate:"required"`
}

func (*ExportAuditProject) Configure(rc *exl.WriteConfig) {}
func ExportAuditProjectHandler(ctx iris.Context) {
	var RequestParams ExportAuditProjectRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var serve dao.Common[dao.SystemProject]
	queryMap := map[string]interface{}{}
	if len(RequestParams.Ids) > 0 {
		queryMap["id"] = RequestParams.Ids
	}
	queryMap["enum_type"] = RequestParams.EnumType
	if exportData, err := serve.FindAll(queryMap); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		exportLists := make([]*ExportAuditProject, len(exportData))
		for i, export := range exportData {
			exportLists[i] = &ExportAuditProject{}
			exportLists[i].ProjectId = export.ProjectId
			exportLists[i].EnumType = export.EnumType
			exportLists[i].WorkProjectId = export.WorkProjectId
			exportLists[i].Title = export.Title
			exportLists[i].OnlineDateTime = export.OnlineDateTime
			exportLists[i].OfflineDateTime = export.OfflineDateTime
			exportLists[i].Category = export.Category
			exportLists[i].SlideShowSort = export.SlideShowSort
			exportLists[i].Sort = export.Sort
			exportLists[i].Limit = export.Limit
			exportLists[i].LowerLimit = export.LowerLimit
			exportLists[i].CountdownAnswer = export.CountdownAnswer
			exportLists[i].Cd = export.Cd
			exportLists[i].DayLimit = export.DayLimit
			exportLists[i].DayGiveUpLimit = export.DayGiveUpLimit
			exportLists[i].GiveUpReasons = export.GiveUpReasons
			exportLists[i].ProjectPrice = export.ProjectPrice
			exportLists[i].Describe = export.Describe
			exportLists[i].AuditQuickTemplate = export.AuditQuickTemplate
			exportLists[i].RejectionTimePeriod = export.RejectionTimePeriod
			exportLists[i].CtrlIncrementUnit = export.CtrlIncrementUnit
			exportLists[i].CtrlDecreaseUnit = export.CtrlDecreaseUnit
			exportLists[i].OpenPerm = export.OpenPerm
			exportLists[i].ClosePerm = export.ClosePerm
		}

		unix := time.Now().UnixNano()
		if err := exl.Write(fmt.Sprintf("./export/export_audit_project_records_%d.xlsx", unix), exportLists); err != nil {
			fmt.Println("write excel err:" + err.Error())
			return
		}
		tempFilename := fmt.Sprintf("./export/export_audit_project_records_%d.xlsx", unix)
		//删除本地临时文件
		defer os.Remove(tempFilename)
		bucketClient := oss.BucketClient{}
		readFile, _ := ioutil.ReadFile(fmt.Sprintf("./export/export_audit_project_records_%d.xlsx", unix))
		bucketClient.UpBytes(readFile, fmt.Sprintf("task-assign/export/export_audit_project_records_%d.xlsx", unix))
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: fmt.Sprintf("%s/task-assign/export/export_audit_project_records_%d.xlsx", utils.ServerConf.AliOssConf.CallBackHost, unix)})
		return
	}
}

type ProjectSpecialClassificationEditRequest struct {
	SpecialClassification     string `json:"special_classification" validate:"required"`
	SpecialClassificationName string `json:"special_classification_name" validate:"required"`
}

func ProjectSpecialClassificationEditHandler(ctx iris.Context) {
	var RequestParams ProjectSpecialClassificationEditRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	Redis.RedisGClient.Set(fmt.Sprintf("SpecialClassification_%s", RequestParams.SpecialClassification), RequestParams.SpecialClassificationName, 0)
	ctx.JSON(utils.ResponseOK())
	return
}

type ProjectSpecialClassificationEditResponse struct {
	SpecialClassificationOneName string `json:"special_classification_one_name"`
	SpecialClassificationTwoName string `json:"special_classification_two_name"`
}

func ProjectSpecialClassificationDetailHandler(ctx iris.Context) {
	var Resp ProjectSpecialClassificationEditResponse
	Resp.SpecialClassificationOneName = Redis.RedisGClient.Get("SpecialClassification_1").Val()
	Resp.SpecialClassificationTwoName = Redis.RedisGClient.Get("SpecialClassification_2").Val()

	ctx.JSON(utils.ResponseData(Resp))
	return
}
